{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# react代理的应用"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 基于通义千问原生接口的ReAct代理实现\n",
    "\n",
    "* 具体的实现方法见课件《9-react代理的国内大模型实现》"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "import requests\n",
    "import json\n",
    "from langchain.utilities import PythonREPL\n",
    "from datetime import datetime\n",
    "from langchain_core.utils.function_calling import convert_to_openai_tool\n",
    "from langchain_core.output_parsers import JsonOutputParser\n",
    "from dashscope import Generation\n",
    "import dashscope\n",
    "from langchain.tools.render import render_text_description\n",
    "from operator import itemgetter\n",
    "from langchain_core.tools import tool\n",
    "import pandas as pd\n",
    "from bs4 import BeautifulSoup\n",
    " \n",
    "dashscope.api_key = \"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "class react_tongyi():\n",
    "\n",
    "    def __init__(self, tool_list):\n",
    "        self.tool_list=tool_list\n",
    "        self.tools = [convert_to_openai_tool(i) for i in tool_list]\n",
    "        self.tool_name=[i[\"function\"][\"name\"] for i in self.tools]\n",
    "        self.parser = JsonOutputParser()\n",
    "\n",
    "    def prompt_ty(self,content):\n",
    "        system_prompt_t=f\"\"\"Use the following format:\n",
    "Question: the input question you must answer\n",
    "Thought: you should always think about what to do\n",
    "Action: the action to take in order, should be one of {self.tool_name}\n",
    "Action Input: the input to the action\n",
    "Observation: the result of the action\n",
    "... (this Thought/Action/Action Input/Observation can repeat N times)\n",
    "Thought: I now know the final answer\n",
    "Final Answer: the final answer to the original input question\n",
    "\n",
    "Begin!\n",
    "        \n",
    "Question: {content}\n",
    "Thought:\"\"\"\n",
    "        prompt=[{\"role\":\"system\",\"content\":\"Answer the following questions as best you can. You have access to the following tools\"}]\n",
    "        prompt.append({\"role\":\"user\",\"content\":system_prompt_t})\n",
    "        return prompt\n",
    "    \n",
    "    def get_response_t(self,messages):\n",
    "        response = Generation.call(\n",
    "            model='qwen-turbo',\n",
    "            messages=messages,\n",
    "            tools=self.tools,\n",
    "            result_format='message', # 将输出设置为message形式\n",
    "        )\n",
    "        return response\n",
    "    \n",
    "    def parser_content(self,out_content):\n",
    "        return {\"name\":out_content.split(\"\\nAction: \")[1].split(\"\\nAction\")[0],\"arguments\": self.parser.parse(out_content.split(\"Input: \")[1])}\n",
    "    \n",
    "    def tool_chain(self,model_output):\n",
    "        tool_map = {tool.name: tool for tool in self.tool_list}\n",
    "        chosen_tool = tool_map[model_output[\"name\"]]\n",
    "        return itemgetter(\"arguments\") | chosen_tool\n",
    "    \n",
    "    def invoke(self,input_p):\n",
    "        prompt=self.prompt_ty(input_p)\n",
    "\n",
    "        for i in range(0,5):\n",
    "            res=self.get_response_t(prompt)\n",
    "            res_content=res.output.choices[0].message[\"content\"]\n",
    "            print(res_content)\n",
    "            if res_content.find(\"\\nAction: \") != -1 :\n",
    "                tool_args=self.parser_content(res_content)\n",
    "                tool_out=self.tool_chain(tool_args)\n",
    "                prompt[1][\"content\"]=prompt[1][\"content\"]+res_content+\"\\nObservation: \"+str(tool_out.invoke(tool_args))+\"\\nThought:\"\n",
    "            else:\n",
    "                prompt[1][\"content\"]=prompt[1][\"content\"]+res_content\n",
    "                break\n",
    "\n",
    "        return(prompt[1][\"content\"])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "@tool\n",
    "def multiply(first_int: int, second_int: int) -> int:\n",
    "    \"\"\"将两个整数相乘。\"\"\"\n",
    "    return first_int * second_int\n",
    "\n",
    "@tool\n",
    "def add(first_int: int, second_int: int) -> int:\n",
    "    \"将两个整数相加。\"\n",
    "    return first_int + second_int\n",
    "\n",
    "@tool\n",
    "def exponentiate(base: int, exponent: int) -> int:\n",
    "    \"对底数求指数幂。\"\n",
    "    return base**exponent"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "tools = [multiply,add,exponentiate]\n",
    "chuxing=react_tongyi(tools)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " 我们需要先执行乘法，然后加法，最后对结果求2次幂。这涉及到的操作是先乘法，后加法，再指数运算。我会使用`multiply`和`add`工具来完成前两步，然后使用`exponentiate`工具计算最终结果。\n",
      "Action: multiply\n",
      "Action Input: {\"first_int\": 7, \"second_int\": 6}\n",
      "乘法的结果是42。接下来，我需要将这个结果与5相加，然后对总和求2次幂。\n",
      "Action: add\n",
      "Action Input: {\"first_int\": 5, \"second_int\": 42}\n",
      "加法后的结果是47。现在，我需要对47求2次幂。\n",
      "Action: exponentiate\n",
      "Action Input: {\"base\": 47, \"exponent\": 2}\n",
      "最终答案是2209。\n",
      "Final Answer: 2209.\n"
     ]
    }
   ],
   "source": [
    "res=chuxing.invoke(\"5加7乘以6,然后再求结果的2次幂\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Use the following format:\n",
      "Question: the input question you must answer\n",
      "Thought: you should always think about what to do\n",
      "Action: the action to take in order, should be one of ['multiply', 'add', 'exponentiate']\n",
      "Action Input: the input to the action\n",
      "Observation: the result of the action\n",
      "... (this Thought/Action/Action Input/Observation can repeat N times)\n",
      "Thought: I now know the final answer\n",
      "Final Answer: the final answer to the original input question\n",
      "\n",
      "Begin!\n",
      "        \n",
      "Question: 5加7乘以6,然后再求结果的2次幂\n",
      "Thought: 我们需要先执行乘法，然后加法，最后对结果求2次幂。这涉及到的操作是先乘法，后加法，再指数运算。我会使用`multiply`和`add`工具来完成前两步，然后使用`exponentiate`工具计算最终结果。\n",
      "Action: multiply\n",
      "Action Input: {\"first_int\": 7, \"second_int\": 6}\n",
      "Observation: 42\n",
      "Thought:乘法的结果是42。接下来，我需要将这个结果与5相加，然后对总和求2次幂。\n",
      "Action: add\n",
      "Action Input: {\"first_int\": 5, \"second_int\": 42}\n",
      "Observation: 47\n",
      "Thought:加法后的结果是47。现在，我需要对47求2次幂。\n",
      "Action: exponentiate\n",
      "Action Input: {\"base\": 47, \"exponent\": 2}\n",
      "Observation: 2209\n",
      "Thought:最终答案是2209。\n",
      "Final Answer: 2209.\n"
     ]
    }
   ],
   "source": [
    "print(res)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 基于ReAct代理的出行顾问的实现\n",
    "\n",
    "* 天气与农历工具的实现见课件<8-自定义工具及其应用>部分"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "@tool\n",
    "def tianqi(city: str) -> dict:\n",
    "    \"\"\"查询最近几日的天气情况，包括温度，天气，湿度，风向等\"\"\"\n",
    "    headers ={\"Content-Type\": \"application/x-www-form-urlencoded\"}\n",
    "    url = \"http://apis.juhe.cn/simpleWeather/query\"\n",
    "    params = {\n",
    "        \"key\":\"\", # 在个人中心->我的数据,接口名称上方查看\n",
    "        \"city\":city, # 要查询的城市名称或城市ID\n",
    "    }\n",
    "    resp = requests.get(url,params,headers=headers)\n",
    "    resp_json = json.loads(resp.text)\n",
    "    return resp_json\n",
    "\n",
    "@tool\n",
    "def wannianli(date: str) -> dict:\n",
    "    \"查询指定日期（日期格式如：'2024-04-08'）的信息，包括农历，星期几，假期，生肖，习俗，忌讳等\"\n",
    "    date=date.replace(\"-0\",\"-\")\n",
    "    print(date)\n",
    "    headers ={\"Content-Type\": \"application/x-www-form-urlencoded\"}\n",
    "    url = \"http://v.juhe.cn/calendar/day\"\n",
    "    params = {\n",
    "        \"key\":\"\", # 在个人中心->我的数据,接口名称上方查看\n",
    "        \"date\":date, # 指定日期,格式为YYYY-MM-DD,如月份和日期小于10,则取个位,如:2012-1-1\n",
    "    }\n",
    "    resp = requests.get(url,params,headers=headers)\n",
    "    resp_json = json.loads(resp.text)\n",
    "    return resp_json\n",
    "\n",
    "@tool\n",
    "def get_date() -> str:\n",
    "    \"获取当天的日期\"\n",
    "    return datetime.now().date().strftime('%Y-%m-%d')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2024-4-8\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'reason': 'Success',\n",
       " 'result': {'data': {'animalsYear': '龙',\n",
       "   'weekday': '星期一',\n",
       "   'lunarYear': '甲辰年',\n",
       "   'lunar': '二月三十',\n",
       "   'year-month': '2024-4',\n",
       "   'date': '2024-4-8',\n",
       "   'suit': '结婚.出行.搬家.签订合同.交易.搬新房.开业.栽种.安床.挂匾.拆卸.出火.收养子女.开光',\n",
       "   'avoid': '祈福.安葬.祭祀.作灶.入殓.探病',\n",
       "   'holiday': '',\n",
       "   'desc': ''}},\n",
       " 'error_code': 0}"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "wannianli.invoke({\"date\":'2024-04-08'})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'reason': '查询成功!',\n",
       " 'result': {'city': '南京',\n",
       "  'realtime': {'temperature': '23',\n",
       "   'humidity': '48',\n",
       "   'info': '晴',\n",
       "   'wid': '00',\n",
       "   'direct': '东北风',\n",
       "   'power': '2级',\n",
       "   'aqi': '30'},\n",
       "  'future': [{'date': '2024-05-28',\n",
       "    'temperature': '14/27℃',\n",
       "    'weather': '晴转多云',\n",
       "    'wid': {'day': '00', 'night': '01'},\n",
       "    'direct': '东风'},\n",
       "   {'date': '2024-05-29',\n",
       "    'temperature': '18/27℃',\n",
       "    'weather': '多云转阴',\n",
       "    'wid': {'day': '01', 'night': '02'},\n",
       "    'direct': '东南风'},\n",
       "   {'date': '2024-05-30',\n",
       "    'temperature': '18/22℃',\n",
       "    'weather': '雷阵雨转中雨',\n",
       "    'wid': {'day': '04', 'night': '08'},\n",
       "    'direct': '西北风转东北风'},\n",
       "   {'date': '2024-05-31',\n",
       "    'temperature': '20/30℃',\n",
       "    'weather': '晴转多云',\n",
       "    'wid': {'day': '00', 'night': '01'},\n",
       "    'direct': '东南风转东风'},\n",
       "   {'date': '2024-06-01',\n",
       "    'temperature': '19/27℃',\n",
       "    'weather': '多云转阴',\n",
       "    'wid': {'day': '01', 'night': '02'},\n",
       "    'direct': '东风'}]},\n",
       " 'error_code': 0}"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tianqi.invoke(\"南京\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [],
   "source": [
    "tools = [get_date, tianqi, wannianli]\n",
    "chuxing=react_tongyi(tools)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " 需要查询明天的农历日期\n",
      "Action: wannianli\n",
      "Action Input: {\"date\": \"tomorrow\"}\n",
      "tomorrow\n",
      " 看来直接查询明天的农历日期不行，我需要先获取当前日期，然后加一天得到明天的日期，再进行查询。\n",
      "Action: get_date\n",
      "Action Input: {}\n",
      "知道了今天的日期后，我可以推算出明天的农历日期。\n",
      "Action: wannianli\n",
      "Action Input: {\"date\": \"2024-05-29\"}\n",
      "2024-5-29\n",
      "明天的农历日期是2024年四月廿二。\n",
      "Final Answer: 明天的农历日期是四月廿二。\n"
     ]
    }
   ],
   "source": [
    "res=chuxing.invoke(\"明天农历几号？\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 基于爬虫的百度搜索工具的实现与应用\n",
    "\n",
    "https://zhuanlan.zhihu.com/p/479674917"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [],
   "source": [
    "@tool\n",
    "def baidu_search(keyword : str) -> str:\n",
    "    \"通过搜索引擎查询指定关键词的相关资料\"\n",
    "    headers = {\n",
    "\t\t\"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36\",\n",
    "\t\t\"Accept\": \"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\",\n",
    "\t\t\"Accept-Language\": \"zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7\",\n",
    "\t\t\"Connection\": \"keep-alive\",\n",
    "\t\t\"Accept-Encoding\": \"gzip, deflate\",\n",
    "\t\t\"Host\": \"www.baidu.com\",\n",
    "\t\t# 需要更换Cookie\n",
    "\t\t\"Cookie\": \"BIDUPSID=4EA09413AA348579EBC32BB4171DA6C4; PSTM=1685953325; BAIDUID=4EA09413AA34857921D22606F3465DE3:SL=0:NR=20:FG=1; BD_UPN=12314753; MCITY=-%3A; BDUSS=d4V1kzMVE5TC02V0dzSzBHR0pPZzZjY2xXZ05-YkxPSlFYOTlqVWtlekUxVjFtSVFBQUFBJCQAAAAAAAAAAAEAAAA3oAABd2FuZ3BlbmdlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMRINmbESDZmRX; BDUSS_BFESS=d4V1kzMVE5TC02V0dzSzBHR0pPZzZjY2xXZ05-YkxPSlFYOTlqVWtlekUxVjFtSVFBQUFBJCQAAAAAAAAAAAEAAAA3oAABd2FuZ3BlbmdlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMRINmbESDZmRX; H_PS_PSSID=60269_60278_60282_60287_60296_60253; H_WISE_SIDS=60269_60278_60282_60287_60296_60253; H_WISE_SIDS_BFESS=60269_60278_60282_60287_60296_60253; BAIDUID_BFESS=4EA09413AA34857921D22606F3465DE3:SL=0:NR=20:FG=1; BD_CK_SAM=1; PSINO=3; delPer=0; BA_HECTOR=810l01ak80aha1a101ah0401evoeh21j58flh1v; ZFY=65gS58gkPrLw3aFizT:BRHNeW:AN:A3yhdtUx81zQ4:Aky8:C; shifen[389215454364_77942]=1716797107; BCLID=8729107127908649389; BCLID_BFESS=8729107127908649389; BDSFRCVID=43DOJeC62iPknV7toafpMW8kd_IPxeRTH6ao8FEfGw7FPXyfJA7mEG0P2U8g0KuM8DJTogKKKgOTHICF_2uxOjjg8UtVJeC6EG0Ptf8g0f5; BDSFRCVID_BFESS=43DOJeC62iPknV7toafpMW8kd_IPxeRTH6ao8FEfGw7FPXyfJA7mEG0P2U8g0KuM8DJTogKKKgOTHICF_2uxOjjg8UtVJeC6EG0Ptf8g0f5; H_BDCLCKID_SF=JnIJoD8hJIK3fP36qRojh-40b2T22jnOM6T9aJ5nJDonDtTJKPbMQftXy4cUqPnbQjQkW-tbQpP-HJ7y3R6xytKN2h6waTcQBm6QKl0MLpQWbb0xyUQY3jDzbxnMBMni52OnapTn3fAKftnOM46JehL3346-35543bRTLnLy5KJtMDFRj5-hDTjyDaR-htRX54ofW-oofK-5sh7_bf--D4FrMUTptb3yKCcj2x0y2bbrOfJ9bq5xy5K_hN7l045xbbvlbUnX5qcNMn6HQT3mDlQbbN3i-xuO3gQnWb3cWhvJ8UbSyfbPBTD02-nBat-OQ6npaJ5nJq5nhMJmb67JD-50exbH55uHtRktVx5; H_BDCLCKID_SF_BFESS=JnIJoD8hJIK3fP36qRojh-40b2T22jnOM6T9aJ5nJDonDtTJKPbMQftXy4cUqPnbQjQkW-tbQpP-HJ7y3R6xytKN2h6waTcQBm6QKl0MLpQWbb0xyUQY3jDzbxnMBMni52OnapTn3fAKftnOM46JehL3346-35543bRTLnLy5KJtMDFRj5-hDTjyDaR-htRX54ofW-oofK-5sh7_bf--D4FrMUTptb3yKCcj2x0y2bbrOfJ9bq5xy5K_hN7l045xbbvlbUnX5qcNMn6HQT3mDlQbbN3i-xuO3gQnWb3cWhvJ8UbSyfbPBTD02-nBat-OQ6npaJ5nJq5nhMJmb67JD-50exbH55uHtRktVx5; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; B64_BOT=1; sug=3; sugstore=0; ORIGIN=0; bdime=0; H_PS_645EC=7da2HdXe6gMkTCYHhNWjWjBKf%2F91xi1Bc2ju7gIhGU8jSNH4YjL1%2BaTa6lI; baikeVisitId=c252a4ed-daf5-4079-8ca6-d287e0ffca21; COOKIE_SESSION=454_1_5_9_12_17_1_0_3_7_0_4_76645_0_0_0_1716797758_1716797108_1716799282%7C9%23409189_19_1716797105%7C9; BDSVRTM=34\"\n",
    "\t}\n",
    "    url=\"https://www.baidu.com/s?wd=\"+keyword\n",
    "    response=requests.get(url,headers=headers)\n",
    "    soup = BeautifulSoup(response.text)\n",
    "    text=\"\"\n",
    "    for i in soup.find_all(\"div\",class_=\"result c-container xpath-log new-pmd\"):\n",
    "        try:\n",
    "            text=text+\"tite:\"+i.find(\"a\").text+\"\\n\"\n",
    "            text=text+\"content:\"+i.find(\"span\",class_=\"content-right_2s-H4\").text+\"\\n\"\n",
    "        except:\n",
    "            continue\n",
    "    return text"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [],
   "source": [
    "tools = [baidu_search]\n",
    "chuxing=react_tongyi(tools)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " 我需要搜索最新的信息来找到杭州师范大学现任校长的名字。\n",
      "Action: baidu_search\n",
      "Action Input: {\"keyword\": \"杭州师范大学 现任校长\"}\n",
      "根据搜索结果，我可以确认杭州师范大学的现任校长是尚永丰。他不仅是校长，还可能担任了其他职务，如党委副书记、院士等。\n",
      "\n",
      "Final Answer: 杭州师范大学的现任校长是尚永丰。他同时可能还担任了其他行政职务，如党委副书记等。\n"
     ]
    }
   ],
   "source": [
    "res=chuxing.invoke(\"杭州师范大学现任校长是谁\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Use the following format:\n",
      "Question: the input question you must answer\n",
      "Thought: you should always think about what to do\n",
      "Action: the action to take in order, should be one of ['baidu_search']\n",
      "Action Input: the input to the action\n",
      "Observation: the result of the action\n",
      "... (this Thought/Action/Action Input/Observation can repeat N times)\n",
      "Thought: I now know the final answer\n",
      "Final Answer: the final answer to the original input question\n",
      "\n",
      "Begin!\n",
      "        \n",
      "Question: 杭州师范大学现任校长是谁\n",
      "Thought: 我需要搜索最新的信息来找到杭州师范大学现任校长的名字。\n",
      "Action: baidu_search\n",
      "Action Input: {\"keyword\": \"杭州师范大学 现任校长\"}\n",
      "Observation: tite:校长尚永丰在2023级新生开学典礼上的讲话\n",
      "tite:杭州师范大学学校领导-中国高校库-中国高校之窗\n",
      "content:杭州师范大学党委书记 郭东风 党委副书记、校长 尚永丰 党委副书记 杨政 党委副书记 应飚 纪委书记 李泽泉 党委委员 胡绍华 姜建忠 党委委员、副校长 张杭君 党委委员、副校长 戴丽...\n",
      "tite:杭州师范大学校长尚永丰院士为2023级研究生讲授开学第一课\n",
      "content:”9月11日上午，校长尚永丰院士以“杭州师范大学——过去、现在和未来”为题，围绕现代化大学发展理念和发展要素，科学研究的本质、对待科研的态度以及学术规范等话题，为2023级研究生讲授开学第...\n",
      "tite:尚永丰-杭州师范大学校长介绍→MAIGOO人物\n",
      "tite:杭州师范大学校长尚永丰院士在115周年校庆启动仪式上的讲话\n",
      "tite:奋发有为,超越自我!杭师大新生开学典礼上,校长尚永丰院士...\n",
      "content:杭州师范大学校长尚永丰院士在2021级新生开学典礼上的讲话，全文如下 奋发有为  超越自我 （2021年9月26日）各位老师，亲爱的同学们：大家早上好!兰叶春葳蕤，桂华秋皎洁。在这个天...\n",
      "tite:杭州师范学院更名杭州师范大学揭牌仪式举行\n",
      "tite:浙江3所省属大学校长由院士担任,其中一位还曾在211担任过...\n",
      "content:第三、杭州师范大学 和其他师范类院校不同的是，杭州师范大学的医学教育相对比较有特色，而且该校有自己的医学部，临床医学是浙江省级重点专业。杭州师范大学现任校长就是医学分子...\n",
      "tite:杭州师范学院毕业证历任校长_求职者曙光网\n",
      "tite:知名师范大学迎来新任一把手,非高校管理者出身\n",
      "content:在近日杭州师范大学更新了其官网上的相关信息，在这个更新中可以得知该校已经迎来了新任书记，而这位新任校长在此前一直在杭州市担任一些行政管理工作，在高校中目前没有看出有任何...\n",
      "tite:可以帮我综合评价一下杭州师范大学吗? - 知乎\n",
      "content:看到这张图真的是感慨万千 图中两人分别是原杭州师范大学校长叶高翔（左）和现任校长尚永丰（右）关于...\n",
      "tite:杭州师范大学历史沿革及历任校长简介 - 百度文库\n",
      "tite:最新!浙江8所高校迎来新任校长,1所高校院长暂空\n",
      "tite:林正范 杭州师范大学校长 人物主页 - 牛媒数据\n",
      "content:现任职务: 杭州师范大学校长 简介: 林正范现为浙江省中小学教师专业发展培训指导委员会主任,浙江省教育学会常务副会长,杭州师范大学教师发展研究中心主任,浙江大学兼职博士生导师.姓名:林正范性别...\n",
      "tite:杭州师范大学是几本、是一本还是二本\n",
      "\n",
      "Thought:根据搜索结果，我可以确认杭州师范大学的现任校长是尚永丰。他不仅是校长，还可能担任了其他职务，如党委副书记、院士等。\n",
      "\n",
      "Final Answer: 杭州师范大学的现任校长是尚永丰。他同时可能还担任了其他行政职务，如党委副书记等。\n"
     ]
    }
   ],
   "source": [
    "print(res)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 基于爬虫的头条新闻搜索工具的实现与应用"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "@tool\n",
    "def toutiao_new_search(keyword : str) -> str:\n",
    "    \"通过新闻搜索查询指定关键词的最新资讯\"\n",
    "    headers = {\n",
    "        \"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36\",\n",
    "        \"Accept\": \"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7\",\n",
    "        \"Accept-Language\": \"zh-CN,zh;q=0.9,en;q=0.8\",\n",
    "        \"Connection\": \"keep-alive\",\n",
    "        \"Accept-Encoding\": \"gzip, deflate\",\n",
    "        \"Host\": \"so.toutiao.com\",\n",
    "        # 需要更换Cookie\n",
    "        \"Cookie\": \"tt_webid=7241099634301961765; utm_source=torchlight_preview_test; ttwid=1%7C2cEYeizFUPDRTlgVfnpBXDzZbVBqU47ZoqVkOPUNsng%7C1716808003%7C97ffdfaa8832097f7a26c6bc5853d52fbfc05887470e1bd67d1603537751d996; _tea_utm_cache_4916=undefined; _S_DPR=1.25; _S_IPAD=0; s_v_web_id=verify_lwov5wdv_zdHahoml_zBkB_47vC_9Ie1_Q3HsscEwSeEM; __ac_nonce=066547f0500db9ae978bc; __ac_signature=_02B4Z6wo00f01XgfN4gAAIDAVpj6oP1-21l4PzMAADhX37; __ac_referer=https://so.toutiao.com/search?dvpf=pc&source=search_subtab_switch&keyword=%E6%9D%A8%E5%B9%82&pd=baike&action_type=search_subtab_switch&page_num=0&from=baike&cur_tab_title=baike&search_id=; _S_WIN_WH=954_1018\"\n",
    "    }\n",
    "    url=\"https://so.toutiao.com/search?dvpf=pc&source=input&keyword=\"+keyword+\"&pd=information&action_type=search_subtab_switch&page_num=0&from=news&cur_tab_title=news\"\n",
    "    response=requests.get(url,headers=headers)\n",
    "    soup = BeautifulSoup(response.text)\n",
    "    text=\"\"\n",
    "    for i in soup.find_all(\"div\",class_=\"result-content\")[1:11]:\n",
    "        try:\n",
    "            text=text+\"tite:\"+i.find(\"a\").text+\"\\n\"\n",
    "            text=text+\"content:\"+i.find(\"span\",class_=\"text-underline-hover\").text+\"\\n\"\n",
    "        except:\n",
    "            continue\n",
    "    return text"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [],
   "source": [
    "tools = [baidu_search,toutiao_new_search]\n",
    "chuxing=react_tongyi(tools)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " 由于马云是中国著名的企业家，他作为阿里巴巴集团的创始人，其个人行踪通常不会公开详细公告。不过，我可以尝试查找最新的新闻报道来了解他的公开活动。\n",
      "Action: toutiao_new_search\n",
      "Action Input: {\"keyword\": \"马云 现在 地点\"}\n",
      " 马云最近的行踪似乎在波黑和日本都有出现，特别是在东京，他似乎已经定居，并且参与了一些公共活动，如教学和私人社交。不过，由于名人隐私保护，详细的个人位置信息通常是保密的。因此，我无法提供确切的当前位置，但可以确认他活跃于公共视野中，特别是教育和文化交流领域。\n",
      "\n",
      "Final Answer: 马云最近的动态显示，他可能在日本东京生活，特别是在教育领域有所涉猎，并且也出现在波黑等地。但具体的位置信息可能会因隐私原因而难以获取。他似乎过着较为低调的生活，专注于个人的新角色和兴趣。\n"
     ]
    }
   ],
   "source": [
    "res=chuxing.invoke(\"马云现在在哪里？\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 93,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " 我需要查找比亚迪公司2024年的新款汽车信息，但通常这类信息还未公开发布，所以我可能需要使用新闻搜索来查看最近的相关报道或预测，或者直接在可靠汽车新闻网站上寻找可能的预告。我会先尝试搜索最新的新闻报道。\n",
      "Action: toutiao_new_search\n",
      "Action Input: {\"keyword\": \"比亚迪 2024 新车\"}\n",
      "从搜索结果中，我找到了一些关于比亚迪公司2024年新款汽车的信息。以下是一些亮点：\n",
      "\n",
      "- 比亚迪全新MPV车型，预计搭载DM-i 5.0插电混动技术。\n",
      "- 海豹06 DM-i将在5月28日正式上市，定位B级车。\n",
      "- 宋L系列推出了多款车型，包括204马力版本。\n",
      "- 唐EV荣耀版、唐DM-p荣耀版以及2024款唐DM-p战神版将全系标配云辇-C。\n",
      "- 秦L预计于2024年5月28日上市，售价12万元左右。\n",
      "- 海狮6 PHEV被期待挑战丰田RAV4混合动力。\n",
      "- 比亚迪王朝和海洋网都有新车发布计划。\n",
      "\n",
      "这些信息表明比亚迪在2024年确实有多款新车计划，涵盖了不同细分市场。不过，具体的车型配置、细节和上市时间可能会有所变化，建议关注比亚迪官方发布的信息以获取最准确的消息。\n"
     ]
    }
   ],
   "source": [
    "res=chuxing.invoke(\"byd公司2024年有哪些新型汽车\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
